package sweet_heart;

import com.google.common.base.Preconditions;
import lombok.Getter;
import lombok.Setter;

import java.util.*;

public class ExpressionContext {
    public static final String second = "second";
    public static final String minute = "minute";
    public static final String hour = "hour";
    @Setter
    @Getter
    private ExpressionType expressionType;
    @Setter
    @Getter
    private String expressionString;

    //
    @Setter
    @Getter
    private CommonPart commonPart = null;
    @Setter
    @Getter
    private PeriodicRepetition periodicRepetition = null;
    @Setter
    @Getter
    private Date lastDateTime = null;

    public ExpressionContext(ExpressionType expressionType, String expressionString) {
        this.expressionType = expressionType;
        this.expressionString = expressionString.replace(expressionType.toString(), "").trim();
    }

    /**
     * 表达式解析
     */
    public void parse() {
        //普遍需要解析的是 [00-59 00-59-59 00-23] 这个可以作为通用的解析规则,前三部分

        if (this.expressionType == ExpressionType.right_now) {
            return;
        } else if (this.expressionType == ExpressionType.current_day) {
            this.commonPart = commonPartParse();//[00-59 00-59-59 00-23]
            return;
        } else if (this.expressionType == ExpressionType.periodic_repetition) {
            periodicRepetition = parsePeriodicRepetition();// if null则执行一次就行了
            return;
        } else if (this.expressionType == ExpressionType.day_repetition) {
            this.commonPart = commonPartParse();//[00-59 00-59-59 00-23]
            return;
        } else if (this.expressionType == ExpressionType.week_repetition) {
            this.commonPart = commonPartParse();//[00-59 00-59-59 00-23]
            //
            parseWeekRepetition();
            return;
        } else if (this.expressionType == ExpressionType.month_repetition) {
            this.commonPart = commonPartParse();//[00-59 00-59-59 00-23]
            return;
        } else {
            throw new RuntimeException("else");
        }
    }
    //延迟N再执行 pr .../s00-59/m00-59/h0-23

    public CommonPart commonPartParse() {

        TreeSet<Integer> secondSet = new TreeSet<Integer>();
        TreeSet<Integer> minuteSet = new TreeSet<Integer>();
        TreeSet<Integer> hourSet = new TreeSet<Integer>();
        //
        String[] splits = this.expressionString.split(" ");
        String seconds = splits[0];
        String minutes = splits[1];
        String hours = splits[2];
        //
        ArrayList<String> secondList = new ArrayList<String>();
        secondList.addAll(Arrays.asList(seconds.split("-")));
        secondSet.addAll(secondList);
        //
        ArrayList<String> minuteList = new ArrayList<String>();
        minuteList.addAll(Arrays.asList(minutes.split("-")));
        minuteSet.addAll(minuteList);
        //
        ArrayList<String> hourList = new ArrayList<String>();
        hourList.addAll(Arrays.asList(hours.split("-")));
        hourSet.addAll(hourList);
        //
        CommonPart commonPart = new CommonPart(secondSet, minuteSet, hourSet);
        return commonPart;
    }

    /**
     * 通用匹配
     */
    public void forDay(Date date) {
        //需要计算当前的秒和分和小时已经过去但没有到来的那个时间点
        Preconditions.checkNotNull(this.commonPart, "日期时间秒和分和小时不存在");
        //计算出当前锁所有的秒和分和小时的组合
        //[00-59 00-59-59 00-23] 枚举所有情况进行枚举,但是这种情况很衰
        //所以我们需要进行小时 分 秒进行比较
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //获得当前的小时和分和秒
        int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        //先寻找>=hourOfDay,再寻找minute,再寻找second(这里只是计算不一定必须执行,如果在执行的时候稍微偏差几秒,其实也没有什么的)
        //全部遍历  然后进行比较

        TreeSet secondSet = this.commonPart.getSecondSet();
        TreeSet minuteSet = this.commonPart.getMinuteSet();
        TreeSet hourSet = this.commonPart.getHourSet();

        //可以正向计算
        for (Object o1 :
                hourSet) {
            for (Object o2 :
                    minuteSet) {
                for (Object o3 :
                        secondSet) {

                }
            }

        }


    }

    private PeriodicRepetition parsePeriodicRepetition() {
        if (this.expressionString.equals("")) {
            return null;
        } else {
            PeriodicRepetition periodicRepetition = new PeriodicRepetition();
            String type = null;
            int periodic = -1;
            if (expressionString.startsWith("s")) {
                type = second;
                periodic = Integer.parseInt(expressionString.replace("s", ""));

            } else if (expressionString.startsWith("m")) {
                type = minute;
                periodic = Integer.parseInt(expressionString.replace("s", ""));
            } else if (expressionString.startsWith("h")) {
                type = hour;
                periodic = Integer.parseInt(expressionString.replace("s", ""));
            } else {
                throw new RuntimeException("else");
            }
            periodicRepetition.setType(type);
            periodicRepetition.setPeriodic(periodic);
            return periodicRepetition;
        }

    }

    private void parseWeekRepetition() {
        String[] splits = this.expressionString.split(" ");
//        String seconds = splits[0];秒
//        String minutes = splits[1];分
//        String hours = splits[2];小时
        String weekDaysString = splits[3];
        //
        String[] weekDays = weekDaysString.split("-");
        int[] weekDayInts = new int[weekDays.length];
        //
        int index = 0;
        for (String weekDay :
                weekDays) {
            weekDayInts[index++] = Integer.parseInt(weekDay);
        }
        WeekRepetition weekRepetition = new WeekRepetition();
        weekRepetition.setCommonPart(this.commonPart);
        weekRepetition.setWeekDayInts(weekDayInts);
    }

    private void parseMonthRepetition() {
        String[] splits = this.expressionString.split(" ");
//        String seconds = splits[0];秒
//        String minutes = splits[1];分
//        String hours = splits[2];小时
        String monthDaysString = splits[3];
        //
        String[] monthDays = monthDaysString.split("-");
        int[] monthDayInts = new int[monthDays.length];
        //
        int index = 0;
        for (String monthDay :
                monthDays) {
            monthDayInts[index++] = Integer.parseInt(monthDay);
        }
        MonthRepetition monthRepetition = new MonthRepetition();
        monthRepetition.setCommonPart(this.commonPart);
        monthRepetition.setMonthDayInts(monthDayInts);
    }

    public Date getNextDateTime(Date date) {
        Date now = new Date();//当前的日期时间对象
        //需要记录上一次传入的日期时间对象
        if (lastDateTime == null) {
            if (this.expressionType == ExpressionType.right_now) {
                this.lastDateTime = date;
                return null;//如果返回null则马上执行,如果返回异常则需要根据异常进行判断
            } else if (this.expressionType == ExpressionType.current_day) {
                //需要对秒和分和小时进行解析

            }
            //代表第一次传入时间
            return null;//如果返回null则马上执行,如果返回异常则需要根据异常进行判断

        } else {
            //需要依据上一次,考虑到实时调度的情况那么如果是实时执行则只执行一次
            if (this.expressionType == ExpressionType.right_now) {
                throw new RuntimeException("has ok");
            }
        }
        return null;
    }

}
